La relación entre la salud mental y el empleo, especialmente en los trabajos que nos llevan a pasar muchas horas frente a un ordenador, ha cobrado una importancia creciente en los últimos años debido al aumento de casos de ansiedad, episodios depresivos y estrés laboral, así como otro tipo de enfermedades mentales entre los profesionales de los diferentes sectores. Nuestro seminario aborda este vínculo.
Buscamos analizar cómo el aislamiento social, la falta de contacto humano, la monotonía y la dificultad para separar la vida laboral de la personal contribuyen a deteriorar el bienestar emocional de las personas que trabajan en espacios confinados. Además, queremos comprender por qué estos factores pueden desencadenar problemas como ansiedad, estrés, depresión y trastornos del sueño, y cómo el entorno laboral puede influir en la aparición y agravamiento de estos síntomas.
Demostrar si es que existe, la relación entre episodios depresivos y el teletrabajo, en la actualidad.
Analizar la relación entre el porcentaje de teletrabajo en las comunidades autónomas de España y los indicadores de salud mental de su población.
Evaluar si existen diferencias significativas en la prevalencia de problemas de salud mental entre las Islas Canarias y el conjunto de España en función de la tasa de teletrabajo por provincia o comunidad autónoma.
A continuacion cargamos las siguientes librerias
library(tidyverse)
library(readr)
library(rjson)
library(tidyjson)
library(ggplot2) # Gráficos estáticos
library(plotly) # Gráficos interactivos
library(DT) # Tablas interactivas
library(mapSpain) # Para los mapas
library(gganimate)
Ahora, vamos a leer los archivos. Los datos los hemos recopilado de páginas estatales como el Instituto Nacional de Estadística y “datos.gob” así como de la página estatal del Instituto Canario de Estadística (instac).
Necesitamos cargar el archivo
episodios depresivos.csv.
# Cargamos el archivo CSV de episodios depresivos
depresion_raw <- read_delim(
"input/data/episodios_depresivos.csv",
delim = ";",
escape_double = FALSE,
trim_ws = TRUE,
locale = locale(encoding = "ISO-8859-1")
)
## Rows: 420 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr (5): Sexo, Total Nacional, Comunidades y Ciudades Autónomas, Intensidad ...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Mostramos la tabla para ver cómo ha salido
datatable(depresion_raw)
Necesitamos cargar el archivo
teletrabajo_por_comunidad.csv.
teletrabajo_comunidad_raw <- read_delim(
"input/data/teletrabajo_por_comunidad.csv",
delim = ";",
escape_double = FALSE,
trim_ws = TRUE,
locale = locale(encoding = "ISO-8859-1")
)
## Rows: 200 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr (5): Total Nacional, Comunidades y Ciudades Autónomas, Clase de població...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
datatable(teletrabajo_comunidad_raw)
Necesitamos cargar el archivo
teletrabajoporprovincias.csv.
teletrabajo_provincias_raw <- read_delim(
"INPUT/DATA/teletrabajoporprovincias.csv",
delim = ",",
escape_double = FALSE,
trim_ws = TRUE,
locale = locale(encoding = "ISO-8859-1")
)
## Rows: 16 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): indicadores_nombre, islas_id, islas_nombre
## dbl (2): indicadores_id, teletrabajo_porcentaje_empresas_teletrabajadores_pe...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
datatable(teletrabajo_provincias_raw)
# Este es un proceso un poco diferente a cargar los csvs
# 1. Cargar el archivo JSON
json_data <- fromJSON(file = "input/data/saludmentalcanarias.json")
# 2. Extraer los valores numéricos
valores <- sapply(json_data$data, function(x) x$Valor)
# 3. Extraer los códigos (Isla, Tipo de dato, Estado mental)
codigos_list <- lapply(json_data$data, function(x) x$dimCodes)
codigos_matriz <- do.call(rbind, codigos_list)
# 4. Crear un Data Frame inicial
df_sucio <- data.frame(
Valor = as.numeric(valores),
Codigo_Isla = codigos_matriz[, 1], # Columna 1: Isla
Codigo_Tipo = codigos_matriz[, 2], # Columna 2: Absoluto/Porcentaje
Codigo_Estado = codigos_matriz[, 3] # Columna 3: Estado Mental
)
# 5.
# Leyenda de Islas
leyenda_islas <- data.frame(
Codigo_Isla = json_data$categories[[1]]$codes,
Nombre_Isla = json_data$categories[[1]]$labels
)
# Leyenda de Estados de Salud Mental
leyenda_estado <- data.frame(
Codigo_Estado = json_data$categories[[3]]$codes,
Descripcion_Estado = json_data$categories[[3]]$labels
)
# 6. Unir todo para tener la tabla final, usamos un left join
salud_mental_canarias <- df_sucio %>%
left_join(leyenda_islas, by = "Codigo_Isla") %>%
left_join(leyenda_estado, by = "Codigo_Estado") %>%
# Filtramos para ver porcentajes y el estado "6 o más síntomas" (indicador de problema)
filter(Codigo_Tipo == "Porcentaje") %>%
select(Nombre_Isla, Descripcion_Estado, Valor)
datatable(salud_mental_canarias)
# 1. Cargamos el archivo CON LA CODIFICACIÓN CORRECTA
depresion_raw <- read_delim("input/data/episodios_depresivos.csv",
delim = ";",
escape_double = FALSE,
trim_ws = TRUE,
locale = locale(encoding = "ISO-8859-1"))
# 2. Limpiamos y calculamos porcentajes
depresion_intensidad <- depresion_raw %>%
# Quitamos el Total Nacional
filter(`Comunidades y Ciudades Autónomas` != "Total Nacional") %>%
filter(!is.na(`Comunidades y Ciudades Autónomas`)) %>%
# Convertimos a número
mutate(
Valor_Numerico = as.numeric(gsub(",", ".", gsub("\\.", "", Total)))
) %>%
# Nos quedamos con "Ambos sexos"
filter(Sexo == "Ambos sexos") %>%
# Calculamos el porcentaje
group_by(`Comunidades y Ciudades Autónomas`) %>%
mutate(
Total_Poblacion = Valor_Numerico[`Intensidad depresión` == "TOTAL"],
# ¡AQUÍ ESTÁ EL CAMBIO! Redondeamos a 2 decimales
Porcentaje = round((Valor_Numerico / Total_Poblacion) * 100, 2)
) %>%
ungroup() %>%
# ELIMINAR TOTAL: Quitamos la fila que dice TOTAL
filter(`Intensidad depresión` != "TOTAL") %>%
# Limpiamos nombre de la comunidad
mutate(
Comunidad = trimws(gsub("^[0-9]+", "", `Comunidades y Ciudades Autónomas`))
) %>%
# Seleccionamos columnas finales
select(Comunidad, Intensidad = `Intensidad depresión`, Porcentaje)
# Mostramos la tabla
datatable(depresion_intensidad)
# 1. Filtramos los datos para excluir la categoría "Ninguna" y "No consta"
depresion_con_sintomas <- depresion_intensidad %>%
filter(!Intensidad %in% c("Ninguna", "No consta")) %>%
# Ordenamos las comunidades por el porcentaje total de depresión para un gráfico limpio
group_by(Comunidad) %>%
mutate(Total_Depresion = sum(Porcentaje)) %>%
ungroup() %>%
arrange(desc(Total_Depresion)) %>%
# Convertimos la comunidad a factor para mantener el orden en el gráfico
mutate(Comunidad = factor(Comunidad, levels = unique(Comunidad)))
# 2. Creamos el gráfico de barras agrupadas
grafico_intensidad <- ggplot(depresion_con_sintomas,
aes(x = Comunidad, y = Porcentaje, fill = Intensidad)) +
# Usamos barras con posición dodged (agrupadas lado a lado)
geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.7) +
# Personalizamos colores
scale_fill_brewer(palette = "Reds", direction = -1,
name = "Intensidad",
# Aseguramos que la leyenda vaya en orden de severidad
breaks = c("Grave", "Moderadamente grave", "Moderada", "Leve")) +
# Giramos las coordenadas para que los nombres de las CCAA sean legibles
coord_flip() +
labs(
title = "Prevalencia y Severidad de Episodios Depresivos por CCAA",
subtitle = "El porcentaje es sobre el total de la población de cada Comunidad.",
x = "", # Dejamos el eje X (Comunidades) vacío tras el flip
y = "Porcentaje de Población (%)"
) +
theme_minimal() +
theme(legend.position = "bottom")
# Hacemos el gráfico interactivo
ggplotly(grafico_intensidad)
# 2. Limpiamos para tener SOLO una fila por Comunidad (Trabajadores que teletrabajan)
teletrabajo_ocupados <- teletrabajo_comunidad_raw %>%
# Quitamos Total Nacional y vacíos
filter(`Comunidades y Ciudades Autónomas` != "Total Nacional") %>%
filter(!is.na(`Comunidades y Ciudades Autónomas`)) %>%
# FILTRO CLAVE: Nos quedamos SOLO con el grupo de "Personas ocupadas"
filter(`Clase de población` == "Personas ocupadas") %>%
# Nos quedamos con los que SÍ teletrabajan
filter(Teletrabajo == "Personas que han teletrabajado") %>%
# Limpiamos el nombre de la Comunidad
mutate(
Comunidad = trimws(gsub("^[0-9]+", "", `Comunidades y Ciudades Autónomas`))
) %>%
# Convertimos el porcentaje a número
mutate(
Porcentaje_Teletrabajo_Ocupados = as.numeric(gsub(",", ".", Total))
) %>%
# Seleccionamos solo Nombre y Porcentaje
select(Comunidad, Porcentaje_Teletrabajo_Ocupados)
# Mostramos la tabla (ahora sí, 1 sola fila por CCAA)
datatable(teletrabajo_ocupados)
# 1. Creamos el gráfico de barras horizontal
grafico_teletrabajo <- ggplot(teletrabajo_ocupados,
aes(x = Porcentaje_Teletrabajo_Ocupados,
# Ordenamos las CCAA de menor a mayor porcentaje
y = reorder(Comunidad, Porcentaje_Teletrabajo_Ocupados))) +
geom_col(aes(fill = Porcentaje_Teletrabajo_Ocupados), width = 0.8) +
# Añadimos etiquetas con el porcentaje exacto al final de cada barra
geom_text(aes(label = paste0(Porcentaje_Teletrabajo_Ocupados, "%")),
hjust = -0.1, size = 3) +
scale_fill_gradient(low = "#b2e2e2", high = "#225ea8", name = "Porcentaje") +
labs(
title = "Penetración del Teletrabajo en la Población Ocupada por CCAA",
subtitle = "El porcentaje es sobre el total de personas con empleo.",
x = "Porcentaje de Teletrabajadores (%)",
y = "" # Dejamos el eje Y vacío para que solo se vea el nombre de la CCAA
) +
theme_minimal() +
theme(
legend.position = "none", # La leyenda ya no es necesaria
panel.grid.major.y = element_blank() # Quitamos las líneas horizontales
)
# Hacemos el gráfico interactivo
ggplotly(grafico_teletrabajo)
# 2. Limpiamos y filtramos
teletrabajo_personal_canarias <- teletrabajo_provincias_raw%>%
# A. FILTRO IMPORTANTE: Nos quedamos solo con el indicador de "PERSONAL TOTAL"
filter(indicadores_nombre == "Porcentaje del personal total que es teletrabajador") %>%
# B. Quitamos el total de "Canarias" para ver solo las islas
filter(islas_nombre != "Canarias") %>%
# C. Creamos la columna PROVINCIA (asignando cada isla a la suya)
mutate(
Provincia = case_when(
islas_nombre %in% c("Gran Canaria", "Lanzarote", "Fuerteventura") ~ "Las Palmas",
islas_nombre %in% c("Tenerife", "La Palma", "La Gomera", "El Hierro") ~ "S.C. Tenerife",
TRUE ~ "Otra"
)
) %>%
# D. Seleccionamos y renombramos las columnas finales
select(
Provincia,
Isla = islas_nombre,
Porcentaje_Personal_Teletrabajador = teletrabajo_porcentaje_empresas_teletrabajadores_personal_trabajaba_fuera_locales_empresa
) %>%
# Ordenamos por provincia
arrange(Provincia)
# Mostramos la tabla
datatable(teletrabajo_personal_canarias)
# 1. Creamos el gráfico de barras horizontal agrupado por Provincia
grafico_teletrabajo_islas <- ggplot(teletrabajo_personal_canarias,
aes(x = Porcentaje_Personal_Teletrabajador,
# Ordenamos las islas de menor a mayor teletrabajo dentro de cada provincia
y = reorder(Isla, Porcentaje_Personal_Teletrabajador))) +
# Usamos el color de la barra para diferenciar la Provincia
geom_col(aes(fill = Provincia), width = 0.7) +
# Añadimos etiquetas con el porcentaje exacto
geom_text(aes(label = paste0(Porcentaje_Personal_Teletrabajador, "%")),
hjust = -0.1, size = 3) +
# Separamos el gráfico en dos paneles (facetas) por Provincia
facet_wrap(~ Provincia, scales = "free_y", ncol = 1) + # scales="free_y" ajusta las etiquetas de las Islas a cada panel
scale_fill_manual(values = c("Las Palmas" = "#1b9e77", "S.C. Tenerife" = "#d95f02")) +
labs(
title = "Porcentaje de Personal Teletrabajador en las Islas Canarias",
subtitle = "Comparación por Isla y Provincia.",
x = "Porcentaje de Personal Teletrabajador (%)",
y = ""
) +
theme_minimal() +
theme(
legend.position = "none",
panel.grid.major.y = element_blank(),
strip.text = element_text(face = "bold") # Hace que el título de la provincia sea negrita
)
# Hacemos el gráfico interactivo
ggplotly(grafico_teletrabajo_islas)
# 2. Extracción de valores y códigos
valores <- sapply(json_data$data, function(x) x$Valor)
codigos_list <- lapply(json_data$data, function(x) x$dimCodes)
codigos_matriz <- do.call(rbind, codigos_list)
# 3. Descifrar los NOMBRES (Leyendas)
leyenda_islas <- data.frame(
Codigo_Isla = json_data$categories[[1]]$codes,
Nombre_Isla = trimws(json_data$categories[[1]]$labels)
)
leyenda_estado <- data.frame(
Codigo_Estado = json_data$categories[[3]]$codes,
Descripcion_Estado = trimws(json_data$categories[[3]]$labels)
)
# 4. LIMPIEZA FINAL Y UNIÓN
salud_mental_final <- data.frame(
Valor = as.numeric(valores),
Codigo_Isla = codigos_matriz[, 1],
Codigo_Tipo = codigos_matriz[, 2],
Codigo_Estado = codigos_matriz[, 3]
) %>%
left_join(leyenda_islas, by = "Codigo_Isla") %>%
left_join(leyenda_estado, by = "Codigo_Estado") %>%
# FILTRO 1: Nos quedamos solo con PORCENTAJES
filter(Codigo_Tipo == "Porcentaje") %>%
# --- FILTRO CORREGIDO ---
# Eliminamos cualquier etiqueta que contenga un guion "-" (que indica sub-región)
# y eliminamos el total "CANARIAS".
filter(!str_detect(Nombre_Isla, "-|CANARIAS")) %>%
# ------------------------
# CREAMOS LA COLUMNA PROVINCIA
mutate(
Provincia = case_when(
Nombre_Isla %in% c("Lanzarote", "Fuerteventura", "Gran Canaria") ~ "Las Palmas",
Nombre_Isla %in% c("Tenerife", "La Palma", "La Gomera", "El Hierro") ~ "S.C. Tenerife",
TRUE ~ "Otra"
)
) %>%
# Seleccionamos las columnas finales
select(Provincia, Isla = Nombre_Isla, Estado_Mental = Descripcion_Estado, Porcentaje = Valor) %>%
arrange(Provincia, Isla)
# Mostramos la tabla limpia
datatable(salud_mental_final)
# 1. ORDENACIÓN: Ordenamos las Islas por su porcentaje de riesgo más alto para un gráfico limpio
salud_mental_ordenada <- salud_mental_final %>%
filter(Estado_Mental == "6 o más") %>%
arrange(desc(Porcentaje)) %>%
pull(Isla)
# 2. Creamos el gráfico de barras apiladas
grafico_salud_intensidad <- ggplot(salud_mental_final,
aes(x = Porcentaje,
# Usamos el factor ordenado para la Islas
y = factor(Isla, levels = rev(salud_mental_ordenada)),
# Rellenamos con el estado mental (la pila)
fill = Estado_Mental)) +
geom_bar(stat = "identity", position = "stack", width = 0.8) +
# Usamos facet_wrap para separar el análisis por Provincia
facet_wrap(~ Provincia, scales = "free_y", ncol = 1) +
# Colores: Usamos una escala que va de azul/verde (saludable) a rojo (riesgo)
scale_fill_manual(
name = "Síntomas de Mala Salud Mental",
values = c("0" = "#a1d99b", "1" = "#edf8e9", "2" = "#fed98e", "3" = "#fe9929", "4" = "#d95f0e", "5" = "#993404", "6 o más" = "#7f0000"),
breaks = c("0", "1", "2", "3", "4", "5", "6 o más", "No consta") # Ordenamos la leyenda
) +
labs(
title = "Perfiles de Salud Mental en las Islas Canarias",
subtitle = "Distribución del porcentaje de la población según el número de síntomas (0 a 6 o más).",
x = "Porcentaje de Población (%)",
y = "Isla"
) +
theme_minimal() +
theme(
legend.position = "bottom",
panel.grid.major.y = element_blank(),
strip.text = element_text(face = "bold")
)
# Hacemos el gráfico interactivo
ggplotly(grafico_salud_intensidad)
# 1. Agregamos el porcentaje de depresión por CCAA
# Sumamos todos los porcentajes, excluyendo "Ninguna" y "No consta"
depresion_agregada <- depresion_intensidad %>%
filter(!Intensidad %in% c("Ninguna", "No consta")) %>%
group_by(Comunidad) %>%
summarise(
Porcentaje_Con_Depresion = sum(Porcentaje, na.rm = TRUE),
.groups = 'drop'
)
# 2. Unimos los datos de Depresión y Teletrabajo por la columna "Comunidad"
datos_finales_obj1 <- left_join(depresion_agregada, teletrabajo_ocupados, by = "Comunidad")
# 3. Mostramos la tabla final unida
datatable(datos_finales_obj1)
# Creamos el gráfico de dispersión (scatter plot)
grafico_obj1 <- ggplot(datos_finales_obj1, aes(x = Porcentaje_Teletrabajo_Ocupados, y = Porcentaje_Con_Depresion)) +
geom_point(aes(color = Comunidad), size = 4) + # Puntos coloreados por CCAA
geom_smooth(method = "lm", se = TRUE, color = "#1f77b4", linetype = "dashed") + # Línea de tendencia (LM)
labs(
title = "Relación entre Teletrabajo y Depresión por Comunidad Autónoma",
subtitle = "El eje X es el % de trabajadores que teletrabajan. El eje Y es el % de población con depresión.",
x = "Población que Teletrabaja (% de Ocupados)",
y = "Población con Episodios Depresivos (%)",
color = "Comunidad"
) +
theme_minimal() +
theme(legend.position = "bottom")
# Convertimos a interactivo para ver los nombres de las CCAA al pasar el ratón
ggplotly(grafico_obj1)
# 1. FILTRO: Obtenemos el indicador de ALTO RIESGO de salud mental por Isla
salud_mental_riesgo <- salud_mental_final %>%
filter(Estado_Mental == "6 o más") %>%
select(Isla, Porcentaje_Riesgo = Porcentaje) # Renombramos la columna Valor a Porcentaje_Riesgo
# 2. UNIÓN: Cruzamos el riesgo de salud mental con el porcentaje de teletrabajo
datos_canarias_final <- left_join(teletrabajo_personal_canarias, salud_mental_riesgo, by = "Isla")
# 3. VISUALIZACIÓN: Scatter plot para ver la correlación en ambas provincias
grafico_obj2 <- ggplot(datos_canarias_final, aes(x = Porcentaje_Personal_Teletrabajador, y = Porcentaje_Riesgo)) +
geom_point(aes(color = Isla, text = paste("Isla:", Isla, "<br>Riesgo:", Porcentaje_Riesgo, "%")), size = 5) + # Usamos text para el tooltip de plotly
geom_smooth(method = "lm", se = FALSE, color = "gray", linetype = "dotted") +
# Usamos facet_wrap para separar el análisis por provincia
facet_wrap(~ Provincia, scales = "free") +
labs(
title = "Teletrabajo vs. Riesgo de Problemas de Salud Mental en Canarias",
subtitle = "El eje Y es el porcentaje de población con 6 o más síntomas (alto riesgo).",
x = "Personal Teletrabajador (%)",
y = "Población con Alto Riesgo Mental (%)"
) +
theme_minimal() +
theme(legend.position = "none")
# Convertimos a interactivo para ver los detalles
ggplotly(grafico_obj2, tooltip = "text")